#include <stdio.h>
#include "ioAT89S52.h"
#include "util.h"
#include "hal/button.h"
#include "hal/lcd_driver.h"
#include "hal/uart.h"

/*
|AT(2Byte)|CMD(1Byte)|Length(1Byte)|Data(Length Byte)|
AT
*/
#define FREE_SIGH 0xff
#define A_SIGN 0xfE
#define T_SIGN 0xfD
#define MAX_MESSAGE_LENGTH 0xfc

enum CMD
{
  CMD_STATUS_SET_LINE = 0,
  CMD_STATUS_SET_X,
  CMD_WRITE_LCD,
  CMD_UNSUPPORTED,
  //��������ڲ�����
  CMD_WRITE_LCD_DATA,

};

uint16_t g_cmdLen = 0;


extern volatile uint8_t RecvBuff[];
extern volatile uint16_t uartBuffIndexOrDirectSendLengthLeft;

bool Get16BitNumFromBuff(uint8_t startIndex, uint16_t *retNum);

bool Get8BitNumFromBuff(uint8_t startIndex, uint8_t *resultNum)
{
  uint16_t retNum = 0;
  if (!Get16BitNumFromBuff(startIndex, &retNum))
  {
    return false;
  }

  if (retNum > 256)
  {
    return false;
  }

  *resultNum = (uint8_t)retNum;
  return true;
}

bool Get16BitNumFromBuff(uint8_t startIndex, uint16_t *retNum)
{
  uint16_t result = 0;
  for (int i = startIndex; i < uartBuffIndexOrDirectSendLengthLeft; i++)
  {

    if (RecvBuff[i] < '0' && RecvBuff[i] > '9')
    {
      return false;
    }
    uint8_t recvNum = RecvBuff[i] - '0';
    result = result * 10 + recvNum;
  }
  *retNum = result;
  return true;
}

extern volatile uint8_t isDataRecvDone;

void SerialCmdProcessor()
{
if(isDataRecvDone != 0){
  isDataRecvDone = 0;
  LOGI("I:Done.\r\n");
}
  if (!isEventReady())
  {
    return;
  }

  if (uartBuffIndexOrDirectSendLengthLeft == 0)
  {
    LOGI("E:L=0\r\n");
    SetUARTRecvStatus(UART_STATUS_INSTRUCTION);
    return;
  }

  uint8_t nextStatus = UART_STATUS_INSTRUCTION;

  switch (RecvBuff[0] - '0')
  {
  case CMD_STATUS_SET_LINE: {
    uint8_t line = 0;
    if (uartBuffIndexOrDirectSendLengthLeft != 2)
    {
      LOGI("E:UCL.");LOGI("\r\n");
      break;
    }
    if (RecvBuff[1] < '0' && RecvBuff[1] > '9'){
      LOGI("E:UI_N");LOGI("\r\n");
      break;
    }
    line = RecvBuff[1] - '0';
    if (line > 8)
    {
      LOGI("E:MaxLine=8");LOGI("\r\n");
    }
    else
    {
      LCD19264SetLine(line);
      LOGI("I:A.");LOGI("\r\n");
    }
    
    break;
  }
  case CMD_STATUS_SET_X:
    {
    uint8_t targetX = 0;
    if (uartBuffIndexOrDirectSendLengthLeft < 2)
    {
      LOGI("E:UCL.");LOGI("\r\n");
      break;
    }
    
    if (!Get8BitNumFromBuff(1, &targetX))
    {
      LOGI("E:UI_N");LOGI("\r\n");
      break;
    }

    if (targetX >= 192)
    {
      LOGI("E:Max x=192");LOGI("\r\n");
      break;
    }
    LCD19264SetX(targetX);
    LOGI("I:A.");LOGI("\r\n");
    break;
    }
  case CMD_WRITE_LCD:
    {
    uint16_t recvLen = 0;
    if (uartBuffIndexOrDirectSendLengthLeft < 2)
    {
      LOGI("E:UCL.");LOGI("\r\n");
      break;
    }
    
    if (!Get16BitNumFromBuff(1, &recvLen))
    {
      LOGI("E:UI_N");LOGI("\r\n");
      break;
    }

    if (recvLen > LCD_X_MAX * LCD_LINE_MAX)
    {
      LOGI("E:TL!");LOGI("\r\n");
      break;
    }
    uartBuffIndexOrDirectSendLengthLeft = recvLen;
    nextStatus = UART_STATUS_DATA;
    LOGI("I:DATA.");LOGI("\r\n");
    break;
    }
  default:
    LOGI("E:UCMD!");LOGI("\r\n");
  }

  if(nextStatus != UART_STATUS_DATA){
    uartBuffIndexOrDirectSendLengthLeft = 0;
  }  
  SetUARTRecvStatus(nextStatus);
}

const char *KeyName = "123LUCDR";

uint8_t lastKey = KEY_NO_PRESS;
uint16_t shakeRound = 0;

void ButtonCmdProcessor()
{
  uint8 key = GetKey();
  if (key == KEY_NO_PRESS)
  {
    return;
  }
  
  if(lastKey == key && shakeRound < 3000){
      shakeRound++;
      return;
  }

  LOGI("V:K");
  
  SendCharSync(KeyName[key]);
  
  LOGI("\r\n");
  
  lastKey = key;
  shakeRound = 0;
}

/*
���ͣ�
AT<CMDID>[LEN]<DATA>
Э��������
C:0 ϵͳ������ʶ
E:<DESC> ��������
I:<INFO> ��Ϣ
V:<EVENT> �¼�
*/

int main(void)
{
  AUXR_bit.DISALE = 1;

  //enable WDT
  //WDTRST = 0x1E;
  //WDTRST = 0xE1;

  InitKey();
  InitUART();
  IE_bit.EA = 1;
  LOGI("I:Start.\r\n");
  lcd19264_init();
  LOGI("I:LCD OK.\r\n");
  LOGI("C:0\r\n");
  while (1)
  {
    SerialCmdProcessor();
    ButtonCmdProcessor();
  }
}
